<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/7/23
 * Time: 21:40
 */

namespace app\api\service;
use app\api\model\User;
use app\lib\enum\ScopeEnum;
use app\lib\exception\TokenException;
use app\lib\exception\WxLoginException;
use think\Exception;

class UserToken extends Token
{
    protected $code;
    protected $wxAppId;
    protected $wxAppSecret;
    protected $wxLoginUrl;
    //构造函数
    public function __construct($code)
    {
        $this -> code = $code;
        $this -> wxAppId = config('wx.app_id');
        $this -> wxAppSecret = config('wx.app_secret');
        $this -> wxLoginUrl = sprintf(config('wx.login_url'), $this -> wxAppId, $this -> wxAppSecret, $this -> code);
    }
    //向微信服务器发送请求
    public function getLoginCode()
    {
        $wxResult = curl_get($this -> wxLoginUrl);
        if(!$wxResult) throw new Exception('服务器问题，请稍后重试！');
        if(array_key_exists('errcode', $wxResult)){
            $this -> processLoginError($wxResult);
        }else {
            return $this -> grantToken($wxResult);
        }
    }
    //错误异常外理
    protected function processLoginError($wxResult)
    {
        throw new WxLoginException([
            'msg' => $wxResult['errmsg'],
            'errorCode' => $wxResult['errcode'],
        ]);
    }
    //获取令牌
    protected function grantToken($wxResult)
    {
        $isExistOpenid = Model('User') -> isExistOpenid($wxResult['openid']);
        if($isExistOpenid) {
            $uid = $isExistOpenid['id'];
        }else {
            $uid = $this -> saveOpenid($wxResult);
        }
        //生成令牌
        $cachedValue = $this -> prepareCacheValue($uid, $wxResult);
        return $key = $this -> saveToCache($cachedValue);
    }
    //生成$key并把数据存入缓存中
    protected function saveToCache($cachedValue)
    {
        $key = self::generalToken();
        $value = json_encode($cachedValue);
        $expire_in = config('setting.expire_in');
        $request = cache($key, $value, $expire_in);
        if(!$request) throw new TokenException(['msg' => '缓存系统异常！', 'errorCode' => 10005]);
        return $key;
    }
    //把缓存的数据放在一个数组中
    protected function prepareCacheValue($uid, $wxResult)
    {
        $cacheValue = $wxResult;
        $cacheValue['uid'] = $uid;
        $cacheValue['scope']= ScopeEnum::User;
        return $cacheValue;
    }
    //若没有openid则把openid存到数据库
    protected function saveOpenid($wxResult)
    {
        $createOpenId = User::create(['openid' => $wxResult['openid']]);
        if(!$createOpenId) throw new Exception('数据库服务器异常');
        return $createOpenId['id'];
    }
}